package container

import (
	"github.com/gogf/gf/v2/container/gvar"
	"github.com/gogf/gf/v2/text/gstr"
	"reflect"
)

var Collection = collectionHelper{}

type collectionHelper struct {
}

type collection struct {
	obj interface{}
	v   reflect.Value
	t   reflect.Type
}

func (r collectionHelper) New(obj interface{}) *collection {
	return &collection{
		obj: obj,
		v:   reflect.ValueOf(obj),
		t:   reflect.TypeOf(obj),
	}
}

// Pluck The pluck method retrieves all of the values for a given key:
// 模仿laravel https://laravel.com/docs/9.x/collections#method-pluck
// 用法参见 helper_test.go
func (r *collection) Pluck(key string) *gvar.Var {
	switch r.t.Kind() {
	case reflect.Slice, reflect.Array:
		// fmt.Println(items, "is a slice with element type", typ.Elem())
		var items []interface{}
		valueLens := r.v.Len()
		for i := 0; i < valueLens; i++ {
			val := r.v.Index(i)
			if val.Kind() == reflect.Map {
				value := val.MapIndex(reflect.ValueOf(key))
				if value.IsValid() {
					items = append(items, value.Interface())
				}
			} else {
				if val.Kind() == reflect.Ptr && val.Elem().Kind() == reflect.Struct {
					// fmt.Println("is a ptr")
					val = val.Elem()
				}
				_, ok := val.Type().FieldByName(key)
				if !ok {
					numField := val.Type().NumField()
					for i := 0; i < numField; i++ {
						name := val.Type().Field(i).Name
						tag := val.Type().Field(i).Tag.Get("json")
						if tag != "" {
							tags := gstr.SplitAndTrim(tag, ",")
							tag = tags[0]
							if tag == key {
								value := val.FieldByName(name)
								// fmt.Println("name", i, name, value, tag)
								items = append(items, value.Interface())
								break
							}
						}
					}
				} else {
					// fmt.Println("ok")
					items = append(items, val.FieldByName(key).Interface())
				}
			}
		}
		return gvar.New(items)
	}
	return gvar.New(nil)
}
